package dw.fastfile.common.dto.query;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import dw.fastfile.common.dto.PageRequest;
import dw.fastfile.common.dto.PageResponse;
import dw.fastfile.common.util.SqlUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

/**
 * @description: 分页通用
 * @author: wanghao
 * @create: 2023-05-04 10:45
 **/
public abstract class AbstractPageAble<Condition, Result> {
    @Resource
    private JdbcTemplate jdbcTemplate;

    private Class<Result> resultClass;

    private Class<Result> getResultClass() {
        if (resultClass == null) {
            ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
            resultClass = (Class<Result>) type.getActualTypeArguments()[1];
        }
        return resultClass;
    }

    public PageResponse<Result> queryByPage(PageRequest<Condition> request) {
        return query(request, true);
    }

    public List<Result> queryNoPage(Condition condition) {
        PageRequest<Condition> pageRequest = new PageRequest<>();
        pageRequest.setCondition(condition);

        return this.query(pageRequest, false).getRecordList();
    }

    private PageResponse<Result> query(PageRequest<Condition> request, boolean isPage) {
        List<Result> resultList = Lists.newArrayList();

        PageResponse<Result> pageResponse = new PageResponse<>();
        if (isPage) {
            pageResponse.setPageIndex(request.getPageIndex());
            pageResponse.setPageSize(request.getPageSize());
        }

        Condition condition = request.getCondition();

        // 补充条件
        this.addCondition(condition);

        // 参数
        List<Object> params = Lists.newArrayList();

        StringBuilder sql = this.listSql(condition, params);

        // 排序
        sql.append(this.orderSql());

        // 记录总条数
        int allNum = SqlUtil.countRecord(jdbcTemplate, sql.toString(), params);
        pageResponse.setRecordCount(allNum);

        if (allNum == 0) {
            pageResponse.setRecordList(resultList);
            return pageResponse;
        }

        if (isPage) {
            int start = request.getPageIndex();
            int size = request.getPageSize();
            sql.append(" limit ").append((start - 1) * size).append(", ").append(size);
        }

        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
        if (CollectionUtils.isEmpty(list)) {
            pageResponse.setRecordList(resultList);
            return pageResponse;
        }

        for (Map<String, Object> m : list) {
            resultList.add(this.handleResult(m));
        }

        pageResponse.setRecordList(resultList);

        if (!isPage) {
            return pageResponse;
        }

        // 计算总页数
        pageResponse.setPageCount((allNum - 1) / request.getPageSize() + 1);

        return pageResponse;
    }

    /**
     * 添加条件
     *
     * @param condition 条件
     */
    protected void addCondition(Condition condition) {

    }

    /**
     * 根据条件拼接查询sql
     *
     * @param condition 前端条件
     * @param params    参数
     * @return 拼接好的sql
     */
    protected abstract StringBuilder listSql(Condition condition, List<Object> params);

    /**
     * 排序，最后拼接
     *
     * @return 排序sql
     */
    protected String orderSql() {
        return "";
    }

    /**
     * 处理查询结果，将数据库查的每个对象转换为需要的返回体
     * 默认将map转对象
     *
     * @param dataMap 数据库结果
     * @return 响应数据体
     */
    protected Result handleResult(Map<String, Object> dataMap) {
        return new JSONObject(dataMap).toJavaObject(this.getResultClass());
    }

}
